﻿using System;
using System.Collections.Generic;
using OpenLS.Core.Serialization;
using OpenLS.Spreadsheet.Serialization;

namespace OpenLS.Spreadsheet
{
    ///<summary>
    /// Represents a group of spark lines. It contains properties common to one or more spark lines.
    ///</summary>
    public class SparkLineGroup : IOfficeXmlSerializable
    {
        internal const string Uri = @"{05C60535-1F16-4fd2-B633-F4F36F0B64E0}";
        internal const string xmlName = @"sparklineGroup";
        private readonly List<SparkLine> _sparkLines = new List<SparkLine>();
        private SpreadsheetColor _colorAxis;
        private SpreadsheetColor _colorFirst;
        private SpreadsheetColor _colorHigh;
        private SpreadsheetColor _colorLast;
        private SpreadsheetColor _colorLow;
        private SpreadsheetColor _colorMarkers;
        private SpreadsheetColor _colorNegative;
        private SpreadsheetColor _colorSeries;
        private bool _dateAxis;
        private DisplayBlanksAs _displayEmptyCellsAs;
        private bool _displayHidden;
        private bool _displayXAxis;
        private bool _first;
        private bool _high;
        private bool _last;
        private double _lineWeight = 0.75;
        private bool _low;
        private double? _manualMax;
        private double? _manualMin;
        private bool _markers;
        private SparklineAxisMinMax _maxAxisType;
        private SparklineAxisMinMax _minAxisType;
        private bool _negative;
        private bool _rightToLeft;
        private SparkLineType _type = SparkLineType.Line;
        private string _f;

        public List<SparkLine> SparkLines
        {
            get { return _sparkLines; }
        }

        public SpreadsheetColor ColorAxis
        {
            get { return _colorAxis; }
            set { _colorAxis = value; }
        }

        public SpreadsheetColor ColorFirst
        {
            get { return _colorFirst; }
            set { _colorFirst = value; }
        }

        public SpreadsheetColor ColorHigh
        {
            get { return _colorHigh; }
            set { _colorHigh = value; }
        }

        public SpreadsheetColor ColorLast
        {
            get { return _colorLast; }
            set { _colorLast = value; }
        }

        public SpreadsheetColor ColorLow
        {
            get { return _colorLow; }
            set { _colorLow = value; }
        }

        public SpreadsheetColor ColorMarkers
        {
            get { return _colorMarkers; }
            set { _colorMarkers = value; }
        }

        public SpreadsheetColor ColorNegative
        {
            get { return _colorNegative; }
            set { _colorNegative = value; }
        }

        public SpreadsheetColor ColorSeries
        {
            get { return _colorSeries; }
            set { _colorSeries = value; }
        }

        public bool DateAxis
        {
            get { return _dateAxis; }
            set { _dateAxis = value; }
        }

        public DisplayBlanksAs DisplayEmptyCellsAs
        {
            get { return _displayEmptyCellsAs; }
            set { _displayEmptyCellsAs = value; }
        }

        public bool DisplayHidden
        {
            get { return _displayHidden; }
            set { _displayHidden = value; }
        }

        public bool DisplayXAxis
        {
            get { return _displayXAxis; }
            set { _displayXAxis = value; }
        }

        public bool First
        {
            get { return _first; }
            set { _first = value; }
        }

        public bool High
        {
            get { return _high; }
            set { _high = value; }
        }

        public bool Last
        {
            get { return _last; }
            set { _last = value; }
        }

        public double LineWeight
        {
            get { return _lineWeight; }
            set { _lineWeight = value; }
        }

        public bool Low
        {
            get { return _low; }
            set { _low = value; }
        }

        public double? ManualMaximum
        {
            get { return _manualMax; }
            set { _manualMax = value; }
        }

        public double? ManualMinimum
        {
            get { return _manualMin; }
            set { _manualMin = value; }
        }

        public bool Markers
        {
            get { return _markers; }
            set { _markers = value; }
        }

        public SparklineAxisMinMax MaxAxisType
        {
            get { return _maxAxisType; }
            set { _maxAxisType = value; }
        }

        public SparklineAxisMinMax MinAxisType
        {
            get { return _minAxisType; }
            set { _minAxisType = value; }
        }

        public bool Negative
        {
            get { return _negative; }
            set { _negative = value; }
        }

        public bool RightToLeft
        {
            get { return _rightToLeft; }
            set { _rightToLeft = value; }
        }

        public SparkLineType Type
        {
            get { return _type; }
            set { _type = value; }
        }

        #region IOfficeXmlSerializable Members

        public void ReadXml(ReadContext context)
        {
            using (ReadContext rc = context.Read(SpreadsheetConstants.MicrosoftSpreadsheetNamespace+ xmlName))
            {
                ManualMaximum = rc.GetOptionalDouble("manualMax");
                ManualMinimum = rc.GetOptionalDouble("manualMin");
                LineWeight = rc.GetOptionalDouble("lineWeight", 0.75);
                Type = rc.GetOptionalEnum("type", SparkLineType.Line);
                DateAxis = rc.GetOptionalBoolean("dateAxis", false);

                DisplayEmptyCellsAs = rc.GetOptionalEnum("displayEmptyCellsAs",
                                                          DisplayBlanksAs.Zero);
                Markers = rc.GetOptionalBoolean("markers", false);
                High = rc.GetOptionalBoolean("high", false);
                Low = rc.GetOptionalBoolean("low", false);
                First = rc.GetOptionalBoolean("first", false);
                Last = rc.GetOptionalBoolean("last", false);
                Negative = rc.GetOptionalBoolean("negative", false);
                DisplayXAxis = rc.GetOptionalBoolean("displayXAxis", false);
                DisplayHidden = rc.GetOptionalBoolean("displayHidden", false);
                MinAxisType = rc.GetOptionalEnum("minAxisType", SparklineAxisMinMax.Individual);
                MaxAxisType = rc.GetOptionalEnum("maxAxisType", SparklineAxisMinMax.Individual);

                RightToLeft = rc.GetOptionalBoolean("rightToLeft", false);

                ColorSeries = SpreadsheetColor.ReadColor("colorSeries", rc);
                ColorNegative = SpreadsheetColor.ReadColor("colorNegative", rc);
                ColorAxis = SpreadsheetColor.ReadColor("colorAxis", rc);
                ColorMarkers = SpreadsheetColor.ReadColor("colorMarkers", rc);
                ColorFirst = SpreadsheetColor.ReadColor("colorFirst", rc);
                ColorLast = SpreadsheetColor.ReadColor("colorLast", rc);
                ColorHigh = SpreadsheetColor.ReadColor("colorHigh", rc);
                ColorLow = SpreadsheetColor.ReadColor("colorLow", rc);
                if (rc.ReaderLocalName == "f")
                {
                    var cc = rc.SwitchNamespace(SpreadsheetConstants.ExcelMainNamespace.NamespaceUri, false);
                    this._f = cc.ReadElementString("f");
                }
                SparkLines.Clear();
                SparkLines.AddRange(rc.ReadOptionalListElement<SparkLine>("sparklines", SparkLine.xmlName));
            }
        }

        public void WriteXml(WriteContext context)
        {
            using (WriteContext rc = context.Write(SpreadsheetConstants.MicrosoftSpreadsheetNamespace+ xmlName))
            {
                rc.SetOptionalDouble("manualMax", ManualMaximum);
                rc.SetOptionalDouble("manualMin", ManualMinimum);
                rc.SetOptionalDouble("lineWeight", LineWeight, 0.75);
                rc.SetOptionalEnum("type", Type, SparkLineType.Line);
                rc.SetOptionalBoolean("dateAxis", DateAxis, false);

                rc.SetOptionalEnum("displayEmptyCellsAs", DisplayEmptyCellsAs, DisplayBlanksAs.Zero);
                rc.SetOptionalBoolean("markers", Markers, false);
                rc.SetOptionalBoolean("high", High, false);
                rc.SetOptionalBoolean("low", Low, false);
                rc.SetOptionalBoolean("first", First, false);
                rc.SetOptionalBoolean("last", Last, false);
                rc.SetOptionalBoolean("negative", Negative, false);
                rc.SetOptionalBoolean("displayXAxis", DisplayXAxis, false);
                rc.SetOptionalBoolean("displayHidden", DisplayHidden, false);
                rc.SetOptionalEnum("minAxisType", MinAxisType, SparklineAxisMinMax.Individual);
                rc.SetOptionalEnum("maxAxisType", MaxAxisType, SparklineAxisMinMax.Individual);

                rc.SetOptionalBoolean("rightToLeft", RightToLeft, false);


                WriteOptionalColor(ColorSeries, "colorSeries", rc);

                WriteOptionalColor(ColorNegative, "colorNegative", rc);
                WriteOptionalColor(ColorAxis, "colorAxis", rc);
                WriteOptionalColor(ColorMarkers, "colorMarkers", rc);
                WriteOptionalColor(ColorFirst, "colorFirst", rc);
                WriteOptionalColor(ColorLast, "colorLast", rc);
                WriteOptionalColor(ColorHigh, "colorHigh", rc);
                WriteOptionalColor(ColorLow, "colorLow", rc);
                if (this._f != null)
                {
                    var cc = rc.Switch(SpreadsheetConstants.ExcelMainNamespace);
                    cc.WriteElementString("f", _f);

                }
                using (WriteContext rc2 = rc.Write("sparklines"))
                {
                    rc2.WriteElements(SparkLines);
                }
            }
        }

        #endregion

        private static void WriteOptionalColor(SpreadsheetColor spreadsheetColor, string colorseries, WriteContext rc)
        {
            if (spreadsheetColor == null)
                return;
            spreadsheetColor.WriteXmlAs(colorseries, rc);
        }
    }
}